package cn.ifafu.ifafu.ui.main

import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.map
import androidx.lifecycle.viewModelScope
import cn.ifafu.ifafu.bean.dto.Version
import cn.ifafu.ifafu.bean.vo.Resource
import cn.ifafu.ifafu.entity.GlobalSetting
import cn.ifafu.ifafu.entity.User
import cn.ifafu.ifafu.repository.GlobalSettingRepository
import cn.ifafu.ifafu.repository.OtherRepository
import cn.ifafu.ifafu.repository.UserRepository
import cn.ifafu.ifafu.ui.common.BaseViewModel
import cn.ifafu.ifafu.ui.main.vo.CheckoutResult
import cn.ifafu.ifafu.ui.main.vo.DeleteResult
import cn.ifafu.ifafu.ui.main.vo.MainTheme
import cn.ifafu.ifafu.util.Response
import cn.ifafu.ifafu.util.doGet
import cn.ifafu.ifafu.util.toLiveData
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.DeviceUtils
import com.blankj.utilcode.util.SPUtils
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject

@HiltViewModel
class MainViewModel @Inject constructor(
    private val userRepository: UserRepository,
    private val globalSettingRepository: GlobalSettingRepository,
    private val otherRepository: OtherRepository,
) : BaseViewModel() {

    companion object {
        private const val API_SHOW_COMMENT_URL = "https://ep.woolsen.cn/api/system/config/value/ifafu.showComment"
        private const val SP_KEY_SHOW_COMMENT = "show_comment_config"
        private const val SP_KEY_UPDATE_REMIND_DATE = "update_remind_date"
    }

    private val _checkoutResult = MutableLiveData<CheckoutResult>()
    val checkoutResult: LiveData<CheckoutResult> = _checkoutResult

    private val _deleteResult = MutableLiveData<DeleteResult>()
    val deleteResult = _deleteResult.toLiveData()

    private val _user = MediatorLiveData<User>().apply {
        addSource(_checkoutResult) {
            if (it is CheckoutResult.Success) {
                this.value = it.user
            }
        }
        addSource(_deleteResult) {
            if (it is DeleteResult.CheckTo) {
                this.value = it.user
            }
        }
    }
    val user = _user.toLiveData()
    val isShowComment = user.map { 
        it.school == User.FAFU && SPUtils.getInstance().getBoolean(SP_KEY_SHOW_COMMENT, false)
    }

    private val _theme = MediatorLiveData<MainTheme>().apply {
        addSource(_user) {
            if (it == null) return@addSource
            viewModelScope.launch {
                val theme = globalSettingRepository.get(it.account).theme
                if (theme == GlobalSetting.THEME_OLD) {
                    this@apply.postValue(MainTheme.OLD)
                } else {
                    this@apply.postValue(MainTheme.NEW)
                }
            }
        }
    }
    val theme = _theme.toLiveData()

    private val _showMultiUserDialog = MutableLiveData<Boolean>()
    val showMultiUserDialog = _showMultiUserDialog.toLiveData()

    private val _updateVersion = MutableLiveData<Version?>()
    val updateVersion = _updateVersion.toLiveData()

    private val _isManualCheck = MutableLiveData<Boolean>(true)
    val isManualCheck = _isManualCheck.toLiveData()

    init {
        viewModelScope.launch(Dispatchers.IO) {
            /* 初始化User */
            val user = userRepository.getUser()
            _user.postValue(user)
            /* 提交访问量 */
            val versionName = AppUtils.getAppVersionName()
            val versionCode = AppUtils.getAppVersionCode()
            val systemVersion = DeviceUtils.getSDKVersionCode()
            otherRepository.once(versionCode, versionName, systemVersion)
            /* 获取一键评教开关配置 */
            fetchShowCommentConfig()
        }
    }

    fun getUsersLiveData(): LiveData<List<User>> =
        userRepository.getAllUsersLiveData()

    fun updateSetting() {
        viewModelScope.launch {
            val theme = globalSettingRepository.get().theme
            if (theme == GlobalSetting.THEME_OLD) {
                _theme.postValue(MainTheme.OLD)
            } else {
                _theme.postValue(MainTheme.NEW)
            }
        }
    }

    /**
     * 添加账号成功
     * 重新获取账号管理Dialog数据（配合LiveData自动更新数据，无需手动刷新），刷新界面元素
     */
    fun addAccountSuccess() {
        viewModelScope.launch {
            val user = userRepository.getUser()
            if (user != null) {
                _checkoutResult.postValue(CheckoutResult.Success(user))
            }
        }
    }

    fun deleteUser(user: User) {
        viewModelScope.launch {
            val currentUser = _user.value
            userRepository.deleteUserByAccount(user.account)
            if (user.account != currentUser?.account) { //不为当前用户，则提示删除成功
                _deleteResult.postValue(DeleteResult.Success)
                return@launch
            }
            //若删除的账号为当前正在使用账号，则切换到其他账号
            val nextUser = userRepository.getUser()
            if (nextUser == null) { //不存在其他账号，跳转到登录界面
                _deleteResult.postValue(DeleteResult.NeedLogin)
                return@launch
            } else {
                _deleteResult.postValue(DeleteResult.CheckTo(nextUser))
            }
        }
    }

    /**
     * 切换账号
     *
     * @param user 切换至[user]账号
     */
    fun checkoutTo(user: User) {
        _checkoutResult.value = CheckoutResult.Ing
        viewModelScope.launch {
            val currentUser = _user.value
            if (user.account == currentUser?.account) {
                _checkoutResult.postValue(CheckoutResult.Failure("正在使用:${user.account}，无需切换"))
                return@launch
            }
            userRepository.checkTo(user)
            _checkoutResult.postValue(CheckoutResult.Success(user))
            _user.postValue(user)
        }
    }

    /**
     * 手动检查更新
     */
    fun upgradeApp() {
        _isManualCheck.value = true
        checkForUpdate(isManual = true)
    }

    /**
     * 自动检查更新（打开应用时）
     */
    fun checkUpdateOnStart() {
        // 检查今天是否已经提醒过
        val today = java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault())
            .format(java.util.Date())
        val lastRemindDate = SPUtils.getInstance().getString(SP_KEY_UPDATE_REMIND_DATE, "")
        
        if (lastRemindDate == today) {
            // 今天已经提醒过，不再提醒
            return
        }
        
        _isManualCheck.value = false
        checkForUpdate(isManual = false)
    }

    /**
     * 检查更新的通用方法
     */
    private fun checkForUpdate(isManual: Boolean) {
        viewModelScope.launch {
            when (val res = otherRepository.getNewVersion()) {
                is Resource.Success -> {
                    if (res.data.versionCode <= AppUtils.getAppVersionCode()) {
                        if (isManual) {
                            this@MainViewModel.toastInMain("当前为最新版本")
                        }
                    } else {
                        _updateVersion.postValue(res.data)
                    }
                }
                is Resource.Failure -> {
                    if (isManual) {
                        this@MainViewModel.toastInMain(res.message)
                    }
                }
                is Resource.Loading -> {
                    // Handle loading state if needed
                }
            }
        }
    }

    fun hideUpdateDialog() {
        // 如果是自动检查（今日不再提醒），则保存今天的日期
        if (_isManualCheck.value == false) {
            val today = java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault())
                .format(java.util.Date())
            SPUtils.getInstance().put(SP_KEY_UPDATE_REMIND_DATE, today)
        }
        _updateVersion.value = null
    }

    fun showMultiUserDialog() {
        _showMultiUserDialog.value = true
    }

    fun hideMultiUserDialog() {
        _showMultiUserDialog.value = false
    }

    /**
     * 从服务器获取一键评教开关配置
     */
    private fun fetchShowCommentConfig() {
        viewModelScope.launch(Dispatchers.IO) {
            try {
                val response: Response = doGet(API_SHOW_COMMENT_URL)
                if (response.statusCode == 200) {
                    val shouldShow = response.body.trim() == "true"
                    SPUtils.getInstance().put(SP_KEY_SHOW_COMMENT, shouldShow)
                } else {
                    Timber.e("获取一键评教配置失败: ${response.statusCode} ${response.body}")
                }
            } catch (e: Exception) {
                Timber.e(e, "获取一键评教配置失败")
            }
        }
    }
}